/*
 * @Author: jingyitao
 * @Date: 2023-08-26 13:51:41
 * @Last Modified by: jingyitao
 * @Last Modified time: 2023-10-09 08:53:24
 * 在新版本的 axios 中使用 AxiosRequestConfig 类型约束报错时 可以使用 InternalAxiosRequestConfig 做类型约束
 */

import LocalCache from '../storage/index';
import { Toast } from 'antd-mobile';
import axios, { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig, AxiosResponse } from 'axios';

type Result<T> = {
    code: number;
    succeeded: boolean;
    data: T;
    message: string;
};

// 基础配置
export const baseConfig: AxiosRequestConfig = {
    baseURL: 'http://localhost:3000',
    timeout: 60000
};

// 导出 Request 类,可以自定义参数实例化
export class Request {
    // axios 实例
    instance: AxiosInstance;
    // 基础配置
    baseConfig: AxiosRequestConfig = baseConfig;
    constructor(config: AxiosRequestConfig) {
        // 创建实例
        this.instance = axios.create({ ...this.baseConfig, ...config });

        // 请求拦截器
        this.instance.interceptors.request.use(
            (config: InternalAxiosRequestConfig) => {
                // 可以在这里做请求头的配置 如 AppKey、token 等 视项目情况而定
                // const token = LocalCache.getCache('token')
                // config.headers['token'] = token
                return config;
            },
            // 请求出错 全局提示
            (error) => {
                // return Promise.reject(error)
                return Toast.show(error);
            }
        );

        // 响应拦截器
        this.instance.interceptors.response.use(
            (response: AxiosResponse) => {
                // 可以直接返回 服务器返回的 response 也可以做自定义处理
                return response;
            },
            (error) => {
                // 处理常见的 http 错误请求
                let message;
                switch (error.response.status) {
                    case 400:
                        message = '请求错误(400)';
                        break;
                    case 401:
                        message = '未授权，请重新登录(401)';
                        // 这里可以做清空storage并跳转到登录页的操作
                        break;
                    case 403:
                        message = '拒绝访问(403)';
                        break;
                    case 404:
                        message = '请求出错(404)';
                        break;
                    case 408:
                        message = '请求超时(408)';
                        break;
                    case 500:
                        message = '服务器错误(500)';
                        break;
                    case 501:
                        message = '服务未实现(501)';
                        break;
                    case 502:
                        message = '网络错误(502)';
                        break;
                    case 503:
                        message = '服务不可用(503)';
                        break;
                    case 504:
                        message = '网络超时(504)';
                        break;
                    case 505:
                        message = 'HTTP版本不受支持(505)';
                        break;
                    default:
                        message = `连接出错(${error.response.status})!`;
                }
                Toast.show(message);
                return Promise.reject(error);
            }
        );
    }

    // 定义请求方法
    public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
        return this.instance.request(config);
    }

    // get 请求 Result<T>
    public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
        return this.instance.get(url, config);
    }

    // post 请求 Result<T>
    public post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
        return this.instance.post(url, data, config);
    }

    // put 请求 Result<T>
    public put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
        return this.instance.put(url, data, config);
    }

    // delete 请求 Result<T>
    public delete<T = any>(url: string, config: AxiosRequestConfig): Promise<AxiosResponse<T>> {
        return this.instance.delete(url, config);
    }
}

// 导出一个实例对象
export default new Request({});
